package com.gitee.wsl.common.chart.sample

import android.content.Context
import android.graphics.Canvas
import android.graphics.LinearGradient
import android.graphics.PointF
import android.graphics.RectF
import android.graphics.Shader
import android.view.MotionEvent
import androidx.core.graphics.withSave
import com.gitee.wsl.common.chart.ChartEnum
import com.gitee.wsl.common.draw.gesture.computator.ChartCommutator
import com.gitee.wsl.common.draw.gesture.ChartTouchHandler
import com.gitee.wsl.common.draw.gesture.ContainerScrollType
import com.gitee.wsl.common.draw.gesture.ZoomType
import com.gitee.wsl.common.draw.gesture.ChartTouch
import com.gitee.wsl.common.draw.area.Viewport
import com.gitee.wsl.common.chart.render.background.grid.PlotGrid
import com.gitee.wsl.common.chart.render.foreground.border.BorderDrawableReader
import com.gitee.wsl.common.chart.render.foreground.info.Anchor
import com.gitee.wsl.common.chart.render.foreground.info.PlotLegend
import com.gitee.wsl.common.chart.render.foreground.info.PlotLegendItem
import com.gitee.wsl.common.chart.render.foreground.info.Title
import com.gitee.wsl.common.chart.render.foreground.info.ToolTip
import com.gitee.wsl.common.chart.render.shape.line.CrossLine
import com.gitee.wsl.android.ui.base.innerRect
import com.gitee.wsl.android.ui.ext.type.clipRect
import com.gitee.wsl.common.ui.draw.type.GridDirection
import com.gitee.wsl.common.ui.draw.type.HorizontalAlign
import com.gitee.wsl.common.ui.draw.type.PanMode
import com.gitee.wsl.common.ui.draw.type.RectType
import com.gitee.wsl.common.ui.draw.type.VerticalAlign
import com.gitee.wsl.mathematics.geometry.shape.Rectangle

import timber.log.Timber


abstract class XChart(var touchCheckAble: com.gitee.wsl.common.ui.api.TouchCheckAble? = null,) : Rectangle(), ChartTouch,
    com.gitee.wsl.common.ui.api.TouchCheckAble {

    val chartCommutator: ChartCommutator = ChartCommutator()

    override var left: Float by chartCommutator.maximumViewport::left

    override var right: Float by chartCommutator.maximumViewport::right

    override var top:Float by chartCommutator.maximumViewport::top

    override var bottom: Float by chartCommutator.maximumViewport::bottom


    // 开放主图表区
    val plotViewport: Viewport by chartCommutator::maximumViewport

    val bodyViewport: Viewport by chartCommutator::bodyViewport

   /* // 开放主图表区
    protected val bodyRect: RectF
        get() = bodyViewport.innerRect*/

    // 开放主图表区网格
    val plotGrid: PlotGrid = PlotGrid()

    // 标题栏
    val plotTitle: Title = Title()

   /* val padding = Padding.none

    // 图的内边距属性
     var paddingTop by padding::top
     var paddingBottom by padding::bottom
     var paddingLeft by padding::left
     var paddingRight by padding::right*/


    //是否显示边框
    val borderReader:BorderDrawableReader by lazy{
        BorderDrawableReader(plotViewport)
    }
    var isShowBorder by borderReader::isShowBorder

    // 是否画背景色
    var isShowBackground by borderReader::isShowBackground

    /**
     * 边框宽度,默认为5px
     */
    var borderWidth: Float
        get() {
            var borderWidth = 0f
            if (isShowBorder) {
                borderWidth = borderReader.strokeWidth
            }
            return borderWidth
        }
        set(width) {
            borderReader.strokeWidth = width
        }

    /**
     * 背景画笔
     *
     * @return 画笔
     */
    var backgroundColor: Int by borderReader::backgroundColor

    //图例类
    val plotLegend: PlotLegend by lazy { PlotLegend(this) }

    //动态图例
    //val legend: Legend = Legend()

    //////////////////////////////////////////////////////////
    //过度变量
    //坐标系原点坐标
    var translateXY = FloatArray(2) { 0.0f }

    //var isZoomEnabled = true
    /*var xScale = 0.0f
        get() = chartCommutator.scaleValueX
    var yScale = 0.0f
        get() = chartCommutator.scaleValueX
    var centerScaleX = 0.0f
        get() = currentViewport.baseCenterX
    var centerScaleY = 0.0f
        get() = currentViewport.baseCenterY*/

    //平移模式下的可移动方向
    var plotPanMode = PanMode.FREE
    ////////////////////////////////////////////////////////

    //是否显示十字交叉线
    val isCrossLineVisible:Boolean get() = crossLine != null
    var crossLine: CrossLine? = null

    //是否平移
    //val isScrollEnabled:Boolean  get() = plotPanMode != DrawEnum.PanMode.NONE


    //限制图表滑动范围
    //var isControlPanRange = true

    val selectHelper: ChartSelectHelper by lazy{ ChartSelectHelper(this) }

    //val isValueSelectionEnabled:Boolean get() = selectHelper != null

    var isInteractive = false

    lateinit var touchHandler: ChartTouchHandler

    var invalidateCallBack: com.gitee.wsl.common.ui.api.InvalidateAble?=null


    val toolTip:ToolTip get() = selectHelper.toolTip

    val maximumViewport: Viewport by chartCommutator::maximumViewport

    val currentViewport: Viewport by chartCommutator::currentViewport

    var isZoomEnabled: Boolean by chartCommutator::isZoomEnabled

    var isScrollEnabled: Boolean by chartCommutator::isScrollEnabled

    var isValueTouchEnabled: Boolean by chartCommutator::isValueTouchEnabled

    var zoomType: ZoomType by chartCommutator::zoomType

    var maxZoom: Float
        get() = chartCommutator.maxZoom
        set(maxZoom) {
            chartCommutator.maxZoom = maxZoom
            invalidateCallBack?.invalidate()
        }
    val zoomLevel: Float
        get() = chartCommutator.zoomLevel

    var isViewportCalculationEnabled: Boolean by chartCommutator::isViewportCalculationEnabled

    var isValueSelectionEnabled: Boolean by chartCommutator::isValueSelectionEnabled

    fun init(context: Context,invalidateCallBack: com.gitee.wsl.common.ui.api.InvalidateAble?=null){
        touchHandler = ChartTouchHandler(context,chartCommutator,touchCheckAble)
        isInteractive = true
        isValueSelectionEnabled = touchCheckAble != null
        this.invalidateCallBack=invalidateCallBack
    }

    /*fun onChartDataChanged(){
        chartCommutator.resetContentRect()
        invalidateCallBack?.invalidate()
    }*/



    ///////////////////////////////////////////////////
    //容器 设置
    var isContainerScrollEnabled:Boolean by chartCommutator::isContainerScrollEnabled

    var containerScrollType: ContainerScrollType
        get() =  touchHandler.containerScrollType
        set(value) {
            touchHandler.containerScrollType = value
        }

     fun setContainerScrollEnabled(
        isContainerScrollEnabled: Boolean,
        containerScrollType: ContainerScrollType
    ) {
        this.isContainerScrollEnabled = isContainerScrollEnabled
        this.containerScrollType = containerScrollType
    }
    /////////////////////////////////////////////////

     override fun handleTouch(event: MotionEvent): Boolean {
        return if (isInteractive) {
            val needInvalidate: Boolean = if (isContainerScrollEnabled) {
                touchHandler.handleTouch(event, containerScrollType)
            } else {
                touchHandler.handleTouch(event)
            }
            /*if (needInvalidate) {
                //ViewCompat.postInvalidateOnAnimation(this)
            }*/
            needInvalidate
        } else {
            false
        }
    }

     fun computeScroll() {
        if (isInteractive) {
            if (touchHandler.computeScroll()) {
                invalidateCallBack?.invalidate()
            }
        }
    }

    
    /**
     * 点击
     */


    /**
     * 开放焦点画笔
     *
     * @return 画笔
     */
    var focusPaint by selectHelper::focusPaint

    /**
     * 点的焦点参数
     *
     * @param point
     * 点
     * @param radius
     * 半径
     */
    open fun showFocusPointF(point: PointF, radius: Float) {
        selectHelper.showFocusPointF(point, radius)
    }

    /**
     * 柱形类的焦点参数
     *
     * @param rect
     * 柱形
     */
    open fun showFocusRectF(rect: RectF) {
        selectHelper.showFocusRectF(rect)
    }


    fun extPointClickRange(i: Int){
        selectHelper.extPointClickRange(i)
    }


    fun showCrossLine(){
        if(crossLine == null)
            crossLine = CrossLine()
    }

    /**
     * 返回当前绘制的是什么类型的图
     * @return 类型
     */
    open fun getType(): ChartEnum.ChartType {
        return ChartEnum.ChartType.NONE
    }

    /**
     * 用于指定绘图区与图范围的内边距。单位为PX值. 即用于确定plotArea范围
     *
     * @param left
     * 绘图区与图左边的保留宽度，用于显示左边轴及轴标题之类
     * @param top
     * 绘图区与图顶部的保留距离，用于显示标题及图例之类
     * @param right
     * 绘图区与图右边的保留宽度，用于显示右边轴及轴标题之类
     * @param bottom
     * 绘图区与图底部的保留距离，用于显示底轴及轴标题之类
     */
    /*fun setPadding(left: Float, top: Float, right: Float, bottom: Float) {
        if (top > 0) paddingTop = top
        if (bottom > 0) paddingBottom = bottom
        if (left > 0) paddingLeft = left
        if (right > 0) paddingRight = right
    }*/

    /**
     * 设置图表绘制范围.
     * @param width
     * 图表宽度
     * @param height
     * 图表高度
     */
     fun setChartRange(width: Float, height: Float) {
        setChartRange(0.0f, 0.0f, width, height)
        Timber.d("chart range change width:$width,height:$height")
    }

    /**
     * 设置图表绘制范围,以指定起始点及长度方式确定图表大小.
     *
     * @param startX
     * 图表起点X坐标
     * @param startY
     * 图表起点Y坐标
     * @param width
     * 图表宽度
     * @param height
     * 图表高度
     */
    open fun setChartRange(startX: Float, startY: Float, width: Float, height: Float) {
        chartCommutator.setChartRange(startX, startY, width, height)
        Timber.d("chart range change ${this.innerRect}")
    }

    /**
     * 返回图中心点坐标
     * @return 坐标
     */
   /* fun getCenterXY(): PointF {
        val point = PointF()
        point.x = this.left + div(this.width, 2f)
        point.y = this.top + div(this.height, 2f)
        return point
    }
*/

    /**
     * 设置绘画时的坐标系原点位置
     * @param x 原点x位置
     * @param y 原点y位置
     */
    /*fun setTranslateXY(x: Float, y: Float) {
        if (!this.isScrollEnabled) return
        translateXY = FloatArray(2)
        translateXY[0] = x
        translateXY[1] = y
    }*/

    /**
     * 计算图的显示范围,依屏幕px值来计算.
     */
    protected open fun calcPlotRange() {
        /*plotViewport.bottom = sub(this.bottom - borderWidth / 2, paddingBottom)
        plotViewport.left = add(this.left + borderWidth / 2, paddingLeft)
        plotViewport.right = sub(this.right - borderWidth / 2, paddingRight)
        plotViewport.top = add(this.top + borderWidth / 2, paddingTop)*/

        //chartCommutator.setCurrentViewport(left, top, right, bottom)
    }

    /**
     * 绘制标题
     */
    protected fun drawTitle(canvas: Canvas) {
        plotTitle.renderTitle(left + borderWidth, right - borderWidth, top + borderWidth, width, plotViewport.top, canvas)
    }

    fun setTitleAlign(align: HorizontalAlign, verticalAlign: VerticalAlign?=null){
        plotTitle.titleHorizontalAlign=align
        verticalAlign?.let { plotTitle.titleVerticalAlign = it }
    }


    /**
     * 绘制批注
     * @param anchorSet 批注集合
     * @param dataID    主数据集id
     * @param childID   子数据集id
     * @param canvas    画布
     * @param x            X坐标点
     * @param y            y坐标点
     * @return 是否有绘制
     */
    protected fun drawAnchor(
        anchorSet: List<Anchor>,
        dataID: Int, childID: Int, canvas: Canvas, x: Float, y: Float, radius: Float
    ): Boolean {
        if (-1 == dataID) return false
        val count = anchorSet.size
        val left: Float = plotViewport.left
        val right: Float = plotViewport.right
        val top: Float = plotViewport.top
        val bottom: Float = plotViewport.bottom
        for (i in 0 until count) {
            val an = anchorSet[i]
            if (an.dataSeriesID == dataID) {
                if (-1 == childID || -1 == an.dataChildID || an.dataChildID == childID) {
                    an.renderAnchor(canvas, x, y, radius, left, top, right, bottom)
                    return true
                }
            }
        }
        return false
    }


    /**
     * 设置图的渐变背景色
     * @param gridDirection    渐变方向
     * @param beginColor 起始颜色
     * @param endColor    结束颜色
     */
    @JvmName("setBackgroundColor1")
    fun setBackgroundColor(gridDirection: GridDirection, beginColor: Int, endColor: Int) {

        //getPlotArea().mPaintBackground.setColor(areaColor);
        if (beginColor == endColor) {
            backgroundColor = beginColor
        } else {
            val linearGradient: LinearGradient =
                if (gridDirection == GridDirection.VERTICAL) {
                    LinearGradient(0f, 0f, 0f, bottom - top, beginColor, endColor, Shader.TileMode.MIRROR)
                } else {
                    LinearGradient(left, bottom, right, top, beginColor, endColor, Shader.TileMode.CLAMP)
                }
            borderReader.backgroundPaint.shader = linearGradient
        }

        //borderReader.backgroundPaint.color = endColor
    }


    /**
     * 显示矩形边框
     */
    fun showBorder(rectType: RectType = RectType.RECT) {
        isShowBorder = true
        borderReader.rectType = rectType
    }

    /**
     * 显示圆矩形边框
     */
    fun showRoundBorder() {
       showBorder(RectType.ROUNDRECT)
    }

    fun setTitle(titleStr: String, subTitleStr: String = "") {
        plotTitle.title = titleStr
        plotTitle.subTitle = subTitleStr
    }

    fun setTitleVerticalAlign(verticalAlign: VerticalAlign) {
        plotTitle.titleVerticalAlign = verticalAlign
    }

    fun setTitleHorizontalAlign(horizontalAlign: HorizontalAlign) {
        plotTitle.titleHorizontalAlign = horizontalAlign
    }


    /**
     * 绘制边框
     * @param canvas 画布
     */
    protected fun drawBorder(canvas: Canvas) {
        if (isShowBorder) {
            borderReader.renderBorder("BORDER", canvas, left, top, right, bottom)
        }
    }

    /**
     * 绘制图的背景
     */
    protected fun drawChartBackground(canvas: Canvas) {
        if (isShowBackground) {
            if (isShowBorder) {
                borderReader.renderBorder("CHART", canvas, left, top, right, bottom)
            } else { //要清掉 border的默认间距				
                val borderSpadding = borderReader.innerPadding
                borderReader.renderBorder("CHART", canvas, left - borderSpadding, top - borderSpadding, right + borderSpadding, bottom + borderSpadding)
            }
        }
    }


    /**
     * 设置缩放参数
     * @param xScale    x方向缩放比例
     * @param yScale    y方向缩放比例
     * @param centerX    缩放中心点x坐标
     * @param centerY    缩放中心点y坐标
     */
    /*fun setScale(
        xScale: Float, yScale: Float,
        centerX: Float, centerY: Float
    ) {
        this.xScale = xScale
        this.yScale = yScale
        this.centerScaleX = centerX
        this.centerScaleY = centerY
    }*/

    /*fun getClikedScaleStatus(): Boolean {
        if (!this.isZoomEnabled) return true
        if (xScale.compareTo(0.0f) == 0) return true

        //如果在这范围内，则可以处理点击
        return xScale.compareTo(0.95f) == 1 && xScale.compareTo(1.1f) == -1
    }*/

    /**
     * 缩放图表
     * @param canvas    画布
     */
    private fun scaleChart(canvas: Canvas) {
       /* if (!isEnableScale) return
        if (centerScaleX.compareTo(0.0f) == 1 || centerScaleY.compareTo(0.0f) == 1) {
            canvas.scale(xScale, yScale, centerScaleX, centerScaleY)
            //}else{
            //canvas.scale(mScale, mScale,plotArea.getCenterX(),plotArea.getCenterY());					
        }*/
        if(!isZoomEnabled) return
        canvas.scale(chartCommutator.scaleValueX, chartCommutator.scaleValueY,currentViewport.centerX,currentViewport.centerY)
    }

    //交叉线
    private fun drawDyLine(canvas: Canvas) {
        crossLine?.renderLine(
            canvas, plotViewport.left, plotViewport.top,
            plotViewport.right, plotViewport.bottom
        )
    }

    protected open fun readerBackground(canvas: Canvas){
        // 绘制图背景
        drawChartBackground(canvas)

        //Timber.d("Xchert border reder start")
        //绘制边框
        drawBorder(canvas)

    }

    /**
     * 用于延迟绘制
     * @param canvas    画布
     * @return    是否成功
     * @throws Exception 例外
     */
    protected open fun renderBody(canvas: Canvas): Boolean {
        //selectHelper.render(canvas)
        return true
    }

    protected open fun readerForeground(canvas: Canvas){
        //绘制标题
        drawTitle(canvas)

        //Timber.d("Xchert legend reder start")
        //动态图例
        drawDyLegend(canvas)
    }

    protected open fun readerHighLight(canvas: Canvas){
        //显示焦点
        drawFocusShape(canvas)
        //响应提示
        drawToolTip(canvas)
    }

    /**
     * 全局绘图实例  用render  内部 用draw
     */
    open fun render(canvas: Canvas) {

        Timber.d("Xchert reder start")

        readerBackground(canvas)

            //Timber.d("Xchert post reder start")
            //绘制图表
            canvas.withSave {
                scaleChart(canvas)
                //缩放图表

                Timber.d("clip rect:${plotViewport}")
                canvas.clipRect(plotViewport)
                renderBody(canvas)

                //Timber.d("Xchert dyline reder start")
                //十字交叉线
                drawDyLine(canvas)
                //标注等
                readerHighLight(canvas)
            }

        readerForeground(canvas)

        Timber.d("Xchert reder end")
    }

    private fun drawDyLegend(canvas: Canvas) {
        if (!plotLegend.isVisible) return
        //动态图例
        //plotLegend.setPlotWH(width, height)
        plotLegend.draw(canvas, createLegendData())
    }

    open fun createLegendData(): List<PlotLegendItem> {
        return emptyList()
    }

    /**
     * 绘制焦点形状
     **/
    open fun drawFocusShape(canvas: Canvas) {
        selectHelper.renderFocusShape(canvas)
    }

    /**
     * 绘制提示信息
     */
    open fun drawToolTip(canvas: Canvas) {
        selectHelper.renderToolTip(canvas)
    }

    override fun callTouchListener() {
        touchCheckAble?.callTouchListener()
    }

    override fun checkTouch(touchX: Float, touchY: Float): Boolean {
        return touchCheckAble?.checkTouch(touchX, touchY)?:false
    }

    override fun isTouched(): Boolean {
        return touchCheckAble?.isTouched()?:false
    }

    override fun clearTouch() {
        touchCheckAble?.clearTouch()
    }
}